/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package com.src.uniandes.ecos.tsp.creditscore.jpa;

import com.src.uniandes.ecos.tsp.creditscore.entity.Producto;
import com.src.uniandes.ecos.tsp.creditscore.jpa.exceptions.IllegalOrphanException;
import com.src.uniandes.ecos.tsp.creditscore.jpa.exceptions.NonexistentEntityException;
import com.src.uniandes.ecos.tsp.creditscore.jpa.exceptions.PreexistingEntityException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import com.src.uniandes.ecos.tsp.creditscore.entity.EntidadFinanciera;
import com.src.uniandes.ecos.tsp.creditscore.entity.TipoProducto;
import com.src.uniandes.ecos.tsp.creditscore.entity.ClienteProducto;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author AndhyMao
 */
public class ProductoJpaController {

    public ProductoJpaController() {
        emf = Persistence.createEntityManagerFactory("com.src.uniandes.ecos.tsp.creditscore_CreditScoreEntities_jar_1.0-SNAPSHOTPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Producto producto) throws PreexistingEntityException, Exception {
        if (producto.getClienteProductoList() == null) {
            producto.setClienteProductoList(new ArrayList<ClienteProducto>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            EntidadFinanciera entNit = producto.getEntNit();
            if (entNit != null) {
                entNit = em.getReference(entNit.getClass(), entNit.getEntNit());
                producto.setEntNit(entNit);
            }
            TipoProducto tipCodigo = producto.getTipCodigo();
            if (tipCodigo != null) {
                tipCodigo = em.getReference(tipCodigo.getClass(), tipCodigo.getTipCodigo());
                producto.setTipCodigo(tipCodigo);
            }
            List<ClienteProducto> attachedClienteProductoList = new ArrayList<ClienteProducto>();
            for (ClienteProducto clienteProductoListClienteProductoToAttach : producto.getClienteProductoList()) {
                clienteProductoListClienteProductoToAttach = em.getReference(clienteProductoListClienteProductoToAttach.getClass(), clienteProductoListClienteProductoToAttach.getClienteProductoPK());
                attachedClienteProductoList.add(clienteProductoListClienteProductoToAttach);
            }
            producto.setClienteProductoList(attachedClienteProductoList);
            em.persist(producto);
            if (entNit != null) {
                entNit.getProductoList().add(producto);
                entNit = em.merge(entNit);
            }
            if (tipCodigo != null) {
                tipCodigo.getProductoList().add(producto);
                tipCodigo = em.merge(tipCodigo);
            }
            for (ClienteProducto clienteProductoListClienteProducto : producto.getClienteProductoList()) {
                Producto oldProductoOfClienteProductoListClienteProducto = clienteProductoListClienteProducto.getProducto();
                clienteProductoListClienteProducto.setProducto(producto);
                clienteProductoListClienteProducto = em.merge(clienteProductoListClienteProducto);
                if (oldProductoOfClienteProductoListClienteProducto != null) {
                    oldProductoOfClienteProductoListClienteProducto.getClienteProductoList().remove(clienteProductoListClienteProducto);
                    oldProductoOfClienteProductoListClienteProducto = em.merge(oldProductoOfClienteProductoListClienteProducto);
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findProducto(producto.getProCodigo()) != null) {
                throw new PreexistingEntityException("Producto " + producto + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Producto producto) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Producto persistentProducto = em.find(Producto.class, producto.getProCodigo());
            EntidadFinanciera entNitOld = persistentProducto.getEntNit();
            EntidadFinanciera entNitNew = producto.getEntNit();
            TipoProducto tipCodigoOld = persistentProducto.getTipCodigo();
            TipoProducto tipCodigoNew = producto.getTipCodigo();
            List<ClienteProducto> clienteProductoListOld = persistentProducto.getClienteProductoList();
            List<ClienteProducto> clienteProductoListNew = producto.getClienteProductoList();
            List<String> illegalOrphanMessages = null;
            for (ClienteProducto clienteProductoListOldClienteProducto : clienteProductoListOld) {
                if (!clienteProductoListNew.contains(clienteProductoListOldClienteProducto)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain ClienteProducto " + clienteProductoListOldClienteProducto + " since its producto field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (entNitNew != null) {
                entNitNew = em.getReference(entNitNew.getClass(), entNitNew.getEntNit());
                producto.setEntNit(entNitNew);
            }
            if (tipCodigoNew != null) {
                tipCodigoNew = em.getReference(tipCodigoNew.getClass(), tipCodigoNew.getTipCodigo());
                producto.setTipCodigo(tipCodigoNew);
            }
            List<ClienteProducto> attachedClienteProductoListNew = new ArrayList<ClienteProducto>();
            for (ClienteProducto clienteProductoListNewClienteProductoToAttach : clienteProductoListNew) {
                clienteProductoListNewClienteProductoToAttach = em.getReference(clienteProductoListNewClienteProductoToAttach.getClass(), clienteProductoListNewClienteProductoToAttach.getClienteProductoPK());
                attachedClienteProductoListNew.add(clienteProductoListNewClienteProductoToAttach);
            }
            clienteProductoListNew = attachedClienteProductoListNew;
            producto.setClienteProductoList(clienteProductoListNew);
            producto = em.merge(producto);
            if (entNitOld != null && !entNitOld.equals(entNitNew)) {
                entNitOld.getProductoList().remove(producto);
                entNitOld = em.merge(entNitOld);
            }
            if (entNitNew != null && !entNitNew.equals(entNitOld)) {
                entNitNew.getProductoList().add(producto);
                entNitNew = em.merge(entNitNew);
            }
            if (tipCodigoOld != null && !tipCodigoOld.equals(tipCodigoNew)) {
                tipCodigoOld.getProductoList().remove(producto);
                tipCodigoOld = em.merge(tipCodigoOld);
            }
            if (tipCodigoNew != null && !tipCodigoNew.equals(tipCodigoOld)) {
                tipCodigoNew.getProductoList().add(producto);
                tipCodigoNew = em.merge(tipCodigoNew);
            }
            for (ClienteProducto clienteProductoListNewClienteProducto : clienteProductoListNew) {
                if (!clienteProductoListOld.contains(clienteProductoListNewClienteProducto)) {
                    Producto oldProductoOfClienteProductoListNewClienteProducto = clienteProductoListNewClienteProducto.getProducto();
                    clienteProductoListNewClienteProducto.setProducto(producto);
                    clienteProductoListNewClienteProducto = em.merge(clienteProductoListNewClienteProducto);
                    if (oldProductoOfClienteProductoListNewClienteProducto != null && !oldProductoOfClienteProductoListNewClienteProducto.equals(producto)) {
                        oldProductoOfClienteProductoListNewClienteProducto.getClienteProductoList().remove(clienteProductoListNewClienteProducto);
                        oldProductoOfClienteProductoListNewClienteProducto = em.merge(oldProductoOfClienteProductoListNewClienteProducto);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = producto.getProCodigo();
                if (findProducto(id) == null) {
                    throw new NonexistentEntityException("The producto with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Producto producto;
            try {
                producto = em.getReference(Producto.class, id);
                producto.getProCodigo();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The producto with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<ClienteProducto> clienteProductoListOrphanCheck = producto.getClienteProductoList();
            for (ClienteProducto clienteProductoListOrphanCheckClienteProducto : clienteProductoListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Producto (" + producto + ") cannot be destroyed since the ClienteProducto " + clienteProductoListOrphanCheckClienteProducto + " in its clienteProductoList field has a non-nullable producto field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            EntidadFinanciera entNit = producto.getEntNit();
            if (entNit != null) {
                entNit.getProductoList().remove(producto);
                entNit = em.merge(entNit);
            }
            TipoProducto tipCodigo = producto.getTipCodigo();
            if (tipCodigo != null) {
                tipCodigo.getProductoList().remove(producto);
                tipCodigo = em.merge(tipCodigo);
            }
            em.remove(producto);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Producto> findProductoEntities() {
        return findProductoEntities(true, -1, -1);
    }

    public List<Producto> findProductoEntities(int maxResults, int firstResult) {
        return findProductoEntities(false, maxResults, firstResult);
    }

    private List<Producto> findProductoEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Producto as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Producto findProducto(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Producto.class, id);
        } finally {
            em.close();
        }
    }

    public int getProductoCount() {
        EntityManager em = getEntityManager();
        try {
            return ((Long) em.createQuery("select count(o) from Producto as o").getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
